/**
 * @file TcpApp_server.h
 * @brief TcpApp/TCP server
 * @Author: aple
 * @Date: 2025-9-27 9:20:10
 * @LastEditors: aple
 * @LastEditTime: 2025-9-27 18:37:50
 * @Verision: 1.0.0.0
 **/

#ifndef _TCP_APP_SERVER_H
#define _TCP_APP_SERVER_H

// Dependencies
#include "core/net.h"
#include "server/tcp_server_app_common.h"

// Stack size required to run the TcpApp/TCP server
#ifndef TCP_APP_SERVER_STACK_SIZE
#define TCP_APP_SERVER_STACK_SIZE 650
#elif (TCP_APP_SERVER_STACK_SIZE < 1)
#error TCP_APP_SERVER_STACK_SIZE parameter is not valid
#endif

// Priority at which the TcpApp/TCP server should run
#ifndef TCP_APP_SERVER_PRIORITY
#define TCP_APP_SERVER_PRIORITY OS_TASK_PRIORITY_NORMAL
#endif

// Maximum number of simultaneous connections
#ifndef TCP_APP_SERVER_MAX_CONNECTIONS
#define TCP_APP_SERVER_MAX_CONNECTIONS 2
#elif (TCP_APP_SERVER_MAX_CONNECTIONS < 1)
#error TCP_APP_SERVER_MAX_CONNECTIONS parameter is not valid
#endif

// Idle connection timeout
#ifndef TCP_APP_SERVER_TIMEOUT
#define TCP_APP_SERVER_TIMEOUT 60000
#elif (TCP_APP_SERVER_TIMEOUT < 1000)
#error TCP_APP_SERVER_TIMEOUT parameter is not valid
#endif

// TcpApp/TCP server tick interval
#ifndef TCP_APP_SERVER_TICK_INTERVAL
#define TCP_APP_SERVER_TICK_INTERVAL 1000
#elif (TCP_APP_SERVER_TICK_INTERVAL < 100)
#error TCP_APP_SERVER_TICK_INTERVAL parameter is not valid
#endif

// Maximum length of the client role OID
#ifndef TCP_APP_SERVER_MAX_ROLE_LEN
#define TCP_APP_SERVER_MAX_ROLE_LEN 32
#elif (TCP_APP_SERVER_MAX_ROLE_LEN < 0)
#error TCP_APP_SERVER_MAX_ROLE_LEN parameter is not valid
#endif

// Forward declaration of TcpAppServerContext structure
struct _TcpAppServerContext;
#define TcpAppServerContext struct _TcpAppServerContext

// Forward declaration of TcpAppClientConnection structure
struct _TcpAppClientConnection;
#define TcpAppClientConnection struct _TcpAppClientConnection

// C++ guard
#ifdef __cplusplus
extern "C"
{
#endif

   /**
    * @brief TcpApp/TCP connection state
    **/

   typedef enum
   {
      TCP_APP_CONNECTION_STATE_CLOSED = 0,
      TCP_APP_CONNECTION_STATE_RECEIVE = 2,
      TCP_APP_CONNECTION_STATE_SEND = 3,
      TCP_APP_CONNECTION_STATE_SHUTDOWN_TX = 5,
      TCP_APP_CONNECTION_STATE_SHUTDOWN_RX = 6
   } TcpAppConnectionState;

   /**
    * @brief TCP connection open callback function
    **/

   typedef error_t (*TcpAppServerOpenCallback)(TcpAppClientConnection *connection,
                                               IpAddr clientIpAddr, uint16_t clientPort);

   /**
    * @brief TCP connection close callback function
    **/

   typedef void (*TcpAppServerCloseCallback)(TcpAppClientConnection *connection);

   /**
    * @brief Lock TcpApp table callback function
    **/

   typedef void (*TcpAppServerLockCallback)(TcpAppClientConnection *connection);

   /**
    * @brief Unlock TcpApp table callback function
    **/

   typedef void (*TcpAppServerUnlockCallback)(TcpAppClientConnection *connection);

   /**
    * @brief PDU processing callback function
    **/

   typedef error_t (*TcpAppServerProcessAduCallback)(TcpAppClientConnection *connection,
                                                     const uint8_t *request, size_t requestLen, uint8_t *response,
                                                     size_t *responseLen);

   /**
    * @brief Tick callback function
    **/

   typedef void (*TcpAppServerTickCallback)(TcpAppServerContext *context);

   /**
    * @brief TcpApp/TCP server settings
    **/

   typedef struct
   {
      OsTaskParameters task;                             ///< Task parameters
      NetInterface *interface;                           ///< Underlying network interface
      uint16_t port;                                     ///< TcpApp/TCP port number
      systime_t timeout;                                 ///< Idle connection timeout
      TcpAppServerOpenCallback openCallback;             ///< TCP connection open callback function
      TcpAppServerCloseCallback closeCallback;           ///< TCP connection close callback function
      TcpAppServerLockCallback lockCallback;             ///< Lock TcpApp table callback function
      TcpAppServerUnlockCallback unlockCallback;         ///< Unlock TcpApp table callback function
      TcpAppServerProcessAduCallback processAduCallback; ///< PDU processing callback function
      TcpAppServerTickCallback tickCallback;             ///< Tick callback function
   } TcpAppServerSettings;

   /**
    * @brief TcpApp/TCP client connection
    **/

   struct _TcpAppClientConnection
   {
      TcpAppConnectionState state;                  ///< Connection state
      TcpAppServerContext *context;                 ///< TcpApp/TCP server context
      Socket *socket;                               ///< Underlying socket
      char_t role[TCP_APP_SERVER_MAX_ROLE_LEN + 1]; ///< Client role OID
      systime_t timestamp;                          ///< Time stamp

      uint8_t requestAdu[TCP_APP_TCP_SERVER_MAX_ADU_SIZE];  ///< Request ADU
      size_t requestAduLen;                      ///< Length of the request ADU, in bytes
      size_t requestAduPos;                      ///< Current position in the request ADU
      uint8_t responseAdu[TCP_APP_TCP_SERVER_MAX_ADU_SIZE]; ///< Response ADU
      size_t responseAduLen;                     ///< Length of the response ADU, in bytes
      size_t responseAduPos;                     ///< Current position in the response ADU
   };

   /**
    * @brief TcpApp/TCP server context
    **/

   struct _TcpAppServerContext
   {
      TcpAppServerSettings settings;                                     ///< User settings
      bool_t running;                                                    ///< Operational state of the TcpApp/TCP server
      bool_t stop;                                                       ///< Stop request
      OsEvent event;                                                     ///< Event object used to poll the sockets
      OsTaskParameters taskParams;                                       ///< Task parameters
      OsTaskId taskId;                                                   ///< Task identifier
      Socket *socket;                                                    ///< Listening socket
      TcpAppClientConnection connection[TCP_APP_SERVER_MAX_CONNECTIONS]; ///< Client connections

      uint32_t rxMessageCount;      ///< Total number of messages received
      uint32_t txMessageCount;      ///< Total number of messages sent
      uint32_t commErrorCount;      ///< Total number of communication errors
      uint32_t exceptionErrorCount; ///< Total number of exception errors
   };

   // TcpApp/TCP server related functions
   void TcpAppServerGetDefaultSettings(TcpAppServerSettings *settings);

   error_t TcpAppServerInit(TcpAppServerContext *context, const TcpAppServerSettings *settings);

   error_t TcpAppServerStart(TcpAppServerContext *context);
   error_t TcpAppServerStop(TcpAppServerContext *context);

   void TcpAppServerTask(TcpAppServerContext *context);

   void TcpAppServerDeinit(TcpAppServerContext *context);

// C++ guard
#ifdef __cplusplus
}
#endif

#endif
